<?php

declare(strict_types=1);
/*
 * 自定义助手函数
 * Author: Zane
 * Email: 873934580@qq.com
 * Date: 2023/5/24
 */

use Illuminate\Support\Arr;
use Illuminate\Support\Str;

if (!function_exists('getRoutePrefix')) {
    /**
     * 管理后台路由接口地址前缀
     *
     * @return string
     */
    function getRoutePrefix(): string
    {
        return config('app.prefix', 'system');
    }
}

if (!function_exists('getTableName')) {
    /**
     * 返回数据表名称.
     * 通过模型或者DB操作数据库时laravel会自动添加上前缀信息，则无需这个使用这个方法。
     * 通过sql语句操作时则需要加上前缀信息.
     *
     * @param $tableName
     *
     * @return string
     */
    function getTableName($tableName): string
    {
        $prefix = config('database.prefix');
        if (blank($prefix)) {
            return $tableName;
        }
        if (\Illuminate\Support\Str::startsWith($tableName, $prefix)) {
            return $tableName;
        }

        return $prefix.$tableName;
    }
}

if (!function_exists('infiniteLevel')) {
    /**
     * 将无限分类进行分级别,设定lv值
     *
     * @param string $primary
     * @param array  $arr
     * @param array  $arr2
     * @param int    $perId
     * @param int    $lv
     */
    function infiniteLevel(array $arr, array &$arr2 = [], string $primary = 'id', int $perId = 0, int $lv = 0): void
    {
        if (empty($arr)) {
            return;
        }
        foreach ($arr as $value) {
            if (isset($value['parent_id']) && $value['parent_id'] === $perId) {
                $value['lv'] = $lv;
                $arr2[$value[$primary]] = $value;
                ++$lv;
                infiniteLevel($arr, $arr2, $primary, $value[$primary], $lv--);
            }
        }
    }
}

if (!function_exists('infiniteTree')) {
    /**
     * 树形结构返回数据.
     *
     * @param array  $data
     * @param int    $parentId
     * @param string $parentIdName
     * @param string $childrenName
     *
     * @return array
     */
    function infiniteTree(array $data, int $parentId = 0, string $parentIdName = 'parent_id', string $childrenName = 'children'): array
    {
        if (!$data) {
            return [];
        }
        $result = [];
        $i = 0;
        foreach ($data as $key => $val) {
            if ($parentId === $val[$parentIdName]) {
                unset($data[$key]);
                $result[$i] = $val;
                $result[$i][$childrenName] = infiniteTree($data, $val['id'], $parentIdName, $childrenName);
                ++$i;
            }
        }

        return $result;
    }
}

if (!function_exists('arrayToMap')) {
    /**
     * 返回数组key=>val的map映射关系.
     *
     * @param array  $data
     * @param string $key
     * @param string $val
     *
     * @return array
     */
    function arrayToMap(array $data, string $key = 'id', string $val = ''): array
    {
        $result = [];
        if (0 === count($data)) {
            return $result;
        }
        foreach ($data as $record) {
            if (empty($val)) {
                $result[$record[$key]] = $record;
            } else {
                $result[$record[$key]] = $record[$val];
            }
        }

        return $result;
    }
}

if (!function_exists('addonPath')) {
    /**
     * 插件地址
     *
     * @param $name
     * @param string $path
     *
     * @return string
     */
    function addonPath($name, string $path = ''): string
    {
        return base_path('addons/'.$name.$path);
    }
}

if (!function_exists('addonNamespace')) {
    /**
     * 插件地址
     *
     * @param $name
     *
     * @return string
     */
    function addonNamespace($name): string
    {
        return "Addon\\{$name}";
    }
}

if (!function_exists('modelBuild')) {
    /**
     * 模型构建. 支持指定数据库链接.
     * 有的时候特别懒 并不想为每个表建立模型文件，但是又希望使用模型相关的一些操作，则可以通过这个方法来操作.
     *
     * @param $model
     * @param string $connection
     *
     * @return \App\Models\ModelBuild|\Illuminate\Database\Eloquent\Model|mixed|object
     */
    function modelBuild($model, string $connection = '')
    {
        if ($model instanceof \Illuminate\Database\Eloquent\Model) {
            return $model;
        }
        if (is_string($model)) {
            // 如果带有命名空间则认为是一个 Model
            if (\Illuminate\Support\Str::startsWith($model, ['App', '\App', 'Addons', '\Addons'])) {
                try {
                    return (new \ReflectionClass($model))->newInstance();
                } catch (\ReflectionException $e) {
                }
            }
            // 最后尝试使用model生成
            return \App\Models\ModelBuild::build($model, $connection);
        }

        throw new \App\Exceptions\ServiceException(\App\Exceptions\CommonExceptionConstants::MODEL_ERROR);
    }
}

if (!function_exists('normIds')) {
    /**
     * 规范化ID 可以将 1,2,3,4 类型参数转换为 [1,2,3,4].
     *
     * @param $ids
     *
     * @return array
     */
    function normIds($ids): array
    {
        if (!$ids) {
            return [];
        }
        if (is_string($ids)) {
            $ids = explode(',', $ids);
        }
        $ids = Arr::wrap($ids);

        return array_map(function ($val) {
            return (int) $val;
        }, $ids);
    }
}

if (!function_exists('isSystemField')) {
    /**
     * 验证字段是否为系统字段，系统字段是不允许修改操作的.
     *
     * @param $field
     *
     * @return bool
     */
    function isSystemField($field): bool
    {
        $maps = \App\Enum\DefaultFieldEnum::getMaps();

        return isset($maps[$field]);
    }
}

if (!function_exists('normUrl')) {
    /**
     * 规范url访问地址
     *
     * @param $url
     *
     * @return string
     */
    function normUrl($url): string
    {
        if (blank($url)) {
            return $url;
        }
        if (Str::startsWith('http', $url)) {
            return $url;
        }

        return config('app.url').$url;
    }
}

if (!function_exists('byteFormat')) {
    /**
     * 格式化字节大小.
     *
     * @param number $size      字节数
     * @param string $format    格式化类型，支持KB/MB/GB/TB/PB
     * @param string $delimiter 数字和单位分隔符
     *
     * @return string 格式化后的带单位的大小
     */
    function byteFormat($size, string $format = 'mb', string $delimiter = ''): string
    {
        $format = strtoupper($format);
        $units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];
        $index = array_flip($units);
        $index = $index[$format] ?? 0;
        $divisor = 1024;
        for ($i = $index; 0 < $i; --$i) {
            $divisor = (1024 ** $i);
            if ($size > $divisor) {
                break;
            }
        }
        if (0 === $i) {
            return $size.$delimiter.$units[$i];
        }
        $size = $size / $divisor;

        return round($size, 2).$delimiter.$units[$i];
    }
}

if (!function_exists('_asset')) {
    /**
     * 生成资源访问路径.如设置了CDN访问将返回CND地址.
     *
     * @param string $path   资源路径
     * @param mixed  $secure 设置是否生成安全访问地址
     *
     * @return string
     */
    function _asset(string $path, $secure = null): string
    {
        // TODO 开启cdn访问, 返回cdn的访问地址
        if (1) {
        }

        return asset($path, $secure);
    }
}

if (!function_exists('isTemplateTag')) {
    /**
     * 验证模版指令标签是否存在.
     *
     * @param $tag
     *
     * @return bool
     */
    function isTemplateTag($tag): bool
    {
        $tag = config('view.tag_action.'.$tag);

        return !blank($tag);
    }
}

if (!function_exists('sys')) {
    /**
     * 获取系统配置信息.
     *
     * @param $key
     * @param $default
     *
     * @return null|\Illuminate\Database\Eloquent\HigherOrderBuilderProxy|mixed
     */
    function sys($key, $default = null)
    {
        return \App\Service\ConfigureService::byNameValue($key, $default);
    }
}
